package com.jsz.peini.controller.pay;

import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.alipay.api.internal.util.AlipaySignature;
import com.jsz.peini.bean.activity.ActivityInfo;
import com.jsz.peini.bean.order.OrderInfo;
import com.jsz.peini.bean.order.OrderInfoExample;
import com.jsz.peini.bean.order.PayStream;
import com.jsz.peini.bean.seller.SellerInfo;
import com.jsz.peini.bean.task.TaskInfo;
import com.jsz.peini.bean.user.UserInfo;
import com.jsz.peini.common.constants.Constants;
import com.jsz.peini.common.meta.OrderType;
import com.jsz.peini.common.util.DateTimeUtils;
import com.jsz.peini.common.util.PeiniUtils;
import com.jsz.peini.common.util.alipay.AlipayConfig;
import com.jsz.peini.common.util.alipay.AlipayCore;
import com.jsz.peini.mapper.activity.ActivityInfoMapper;
import com.jsz.peini.mapper.order.OrderInfoMapper;
import com.jsz.peini.mapper.order.PayStreamMapper;
import com.jsz.peini.mapper.seller.SellerInfoMapper;
import com.jsz.peini.mapper.task.TaskInfoMapper;
import com.jsz.peini.mapper.user.UserInfoMapper;
import com.jsz.peini.service.order.OrderInfoService;
import com.jsz.peini.service.task.PartyService;

/**
 * 支付宝支付
 * 
 * @author Han Guohong
 * 
 */
@Controller
@RequestMapping("/payAli")
public class PayByAliController {
	private static final Logger logger = LoggerFactory.getLogger(PayByAliController.class);
	@Resource
	private PayStreamMapper payStreamMapper;
	@Resource
	private OrderInfoMapper orderInfoMapper;
	@Resource
	private TaskInfoMapper taskInfoMapper;
	@Resource
	private UserInfoMapper userInfoMapper;
	@Resource
	private OrderInfoService orderInfoService;
	@Resource
	private SellerInfoMapper sellerInfoMapper;
	@Resource
	private ActivityInfoMapper activityInfoMapper;
	@Resource
	private PartyService partyService;
	
	@ResponseBody
	@RequestMapping(value = "/prePay", produces = "text/plain;charset=UTF-8")
	public String appPre(
			HttpServletRequest request,
			HttpServletResponse response,
			@RequestParam(value = "orderIdStr", required = true) String orderId,
			@RequestParam(value = "userId", required = true) String token)
			throws Exception {

		JSONObject object = new JSONObject();
		try {
			if (StringUtils.isEmpty(orderId)) {
				object.put("resultCode", "0");
				object.put("resultDesc", "订单号不能为空");
				return object.toString();
			}

			if (StringUtils.isBlank(token)) {
				object.put("resultCode", Constants.EXCEPTION);
				object.put("resultDesc", Constants.EXCEPTION_DESC);
				return object.toString();
			}
			JSONObject obj = PeiniUtils.validToken(token);
			if (obj.getInteger("resultCode") != 1) {
				return obj.toJSONString();
			}
			String userId = obj.getString("userId");

			if (orderId.endsWith(",")) {
				orderId = orderId.substring(0, orderId.length() - 1);
			}
			
			OrderInfo title = orderInfoMapper.selectByPrimaryKey(Long.parseLong(orderId));
			String orderCode = title.getOrderCode();
			if(StringUtils.isBlank(orderCode)){
				orderCode = title.getId().toString();
			}

			PayStream payStream = new PayStream();
			String payId = "";
			
			payStream = payStreamMapper.selectByPrimaryKey(orderCode);
			if(payStream != null){//支付流水已经创建过 
				if(payStream.getPayStatus() == 1){
					object.put("resultCode", "0"); object.put("resultDesc","该订单已经支付过啦，请勿重复支付"); 
					return object.toString(); 
				}else{
					/*payStream.setPayTime(new Date()); 
					payId = payStream.getPayId(); */
					
					payStream = new PayStream();
					payId = title.getPayStreamId()+"0";
					payStream.setPayStatus(0);
					payStream.setUserId(userId);
					payStream.setPayTime(new Date());
					payStream.setOrderIdsStr(orderId);
					payStream.setPayId(payId);
					PayStream payStreamTmp = payStreamMapper.selectByPrimaryKey(payId);
					if(payStreamTmp==null){
						payStreamMapper.insertSelective(payStream);
					}else{
						logger.info("重复的订单号====payId>>>"+payId);
					}
					
				}
			}else{
				payStream = new PayStream();
				payId = orderCode;
				payStream.setPayStatus(0);
				// payStream.setPayType(2);
				payStream.setUserId(userId);
				payStream.setPayTime(new Date());
				payStream.setOrderIdsStr(orderId);
				//payId = UUID.randomUUID().toString().replace("-", "");
				payStream.setPayId(orderCode);
				payStreamMapper.insertSelective(payStream);
			}

			String bodyStr = "";
			String titleStr = "";
			//Double totalPay = 0.00;
			BigDecimal totalPay = new BigDecimal("0");

			Integer orderType = title.getOrderType();

			if (orderType == 1) {// 任务订单
				int taskId = title.getTaskInfoId();
				TaskInfo taskInfo = taskInfoMapper
						.selectByPrimaryKey(taskId);
				titleStr = "任务消费：";
				titleStr += taskInfo.getSellerInfoName();
				if (taskInfo.getUserId().equals(userId)) {
					String otherUserId = taskInfo.getOtherUserId();
					UserInfo userInfo = userInfoMapper
							.selectByPrimaryKey(otherUserId);
					bodyStr = DateTimeUtils.formatDateTime2String(
							taskInfo.getTaskAppointedTime(),
							"yyyy-MM-dd HH:mm")
							+ "和" + userInfo.getNickname() + "约会";
				} else {
					String otherUserId = taskInfo.getUserId();
					UserInfo userInfo = userInfoMapper
							.selectByPrimaryKey(otherUserId);
					bodyStr = DateTimeUtils.formatDateTime2String(
							taskInfo.getTaskAppointedTime(),
							"yyyy-MM-dd HH:mm")
							+ "和" + userInfo.getNickname() + "约会";
				}
			} else if (orderType == 2) {// 积分购买优惠券

			} else if (orderType == 3) {// 普通商家订单
				titleStr = "商家消费：";
				int sellerId = title.getSellerInfoId();
				SellerInfo sellerInfo = sellerInfoMapper.selectByPrimaryKey(sellerId);
				bodyStr = DateTimeUtils.formatDateTime2String(title.getOrderTime(),"yyyy-MM-dd HH:mm")+" "+sellerInfo.getSellerName();
			} else if (orderType == 4) {// 任务评价打赏订单
				titleStr = "打赏：";
				String otherId = title.getOtherId();
				UserInfo userInfo = userInfoMapper.selectByPrimaryKey(otherId);
				bodyStr = DateTimeUtils.formatDateTime2String(title.getOrderTime(),"yyyy-MM-dd HH:mm")+" "+userInfo.getNickname();
			}else if (orderType == 6) {// 金币充值订单
				titleStr = "金币充值：";
				bodyStr = DateTimeUtils.formatDateTime2String(title.getOrderTime(),"yyyy-MM-dd HH:mm")+" "+title.getPayMoney();
			}else if (orderType == 7) {// 活动报名订单
				titleStr = "活动报名：";
				String acId = title.getParamId();
				ActivityInfo acInfo = activityInfoMapper.selectByPrimaryKey(acId);
				bodyStr = acInfo.getAcTitle()+"："+DateTimeUtils.formatDateTime2String(title.getOrderTime(),"yyyy-MM-dd HH:mm")+" "+title.getPayMoney();
			}else if(orderType == OrderType.PARTY_PREPAY){  //聚会预付款
				titleStr = "聚会预付款：";
				bodyStr = DateTimeUtils.formatDateTime2String(title.getOrderTime(),"yyyy-MM-dd HH:mm")+" "+title.getPayMoney();
			}else if(orderType == OrderType.PARTY_ORDER){  //聚会付款
				titleStr = "聚会付款：";
				bodyStr = DateTimeUtils.formatDateTime2String(title.getOrderTime(),"yyyy-MM-dd HH:mm")+" "+title.getPayMoney();
			}else if(orderType == OrderType.OFFICAL_PARTY){  //官方聚会付款
				titleStr = "官方聚会付款：";
				bodyStr = DateTimeUtils.formatDateTime2String(title.getOrderTime(),"yyyy-MM-dd HH:mm")+" "+title.getPayMoney();
			}

			//totalPay = ((double) title.getPayMoney()) / 100;
			totalPay = new BigDecimal(title.getPayMoney()).divide(new BigDecimal("100"));

			title.setPayType(3);
			title.setPayStatus(0);
			title.setPayStreamId(payId);
			orderInfoMapper.updateByPrimaryKeySelective(title);
					
			if (titleStr.length() > 100) {
				titleStr = titleStr.substring(0, 100);
			}

			//payStream.setPayMoney(totalPay);
			payStream.setPayMoney(totalPay.doubleValue());
			payStream.setPayCode(UUID.randomUUID().toString().replace("-", ""));
			payStreamMapper.updateByPrimaryKey(payStream);

			JSONObject dataObj = new JSONObject();

			// 公共参数
			Map<String, String> map = new HashMap<String, String>();
			map.put("app_id", AlipayConfig.appId);
			map.put("method", "alipay.trade.app.pay");
			map.put("format", "json");
			map.put("charset", "utf-8");
			map.put("sign_type", "RSA");
			map.put("timestamp", DateTimeUtils.formatDateTime2String(
					new Date(), "yyyy-MM-dd HH:mm:ss"));
			map.put("version", "1.0");

			//PeiniUtils.HOSTURL = "http://4s.dkys.org:10419/pnservice/";
			String notifyUrl = PeiniUtils.HOSTURL + "payAli/notify";
			map.put("notify_url", notifyUrl);

			Map<String, String> m = new HashMap<String, String>();

			m.put("body", bodyStr);
			m.put("subject", titleStr);
			m.put("out_trade_no", payId);
			m.put("timeout_express", "30m");
			m.put("total_amount", totalPay.toString());
			m.put("seller_id", AlipayConfig.partner);
			m.put("product_code", "QUICK_MSECURITY_PAY");

			net.sf.json.JSONObject bizcontentJson = net.sf.json.JSONObject
					.fromObject(m);

			map.put("biz_content", bizcontentJson.toString());
			
			//logger.info(map);
			// 对未签名原始字符串进行签名
			String rsaSign = AlipaySignature.rsaSign(map,
					AlipayConfig.private_key, "utf-8");

			Map<String, String> map4 = new HashMap<String, String>();

			map4.put("app_id", AlipayConfig.appId);
			map4.put("method", "alipay.trade.app.pay");
			map4.put("format", "json");
			map4.put("charset", "utf-8");
			map4.put("sign_type", "RSA");
			map4.put("timestamp",
					DateTimeUtils.formatDateTime2String(
							new Date(), "yyyy-MM-dd HH:mm:ss"));
			map4.put("version", "1.0");
			map4.put("notify_url",
					URLEncoder.encode(notifyUrl, "UTF-8"));
			// 最后对请求字符串的所有一级value（biz_content作为一个value）进行encode，编码格式按请求串中的charset为准，没传charset按UTF-8处理
			map4.put("biz_content",
					URLEncoder.encode(bizcontentJson.toString(), "UTF-8"));

			Map par = AlipayCore.paraFilter(map4); // 除去数组中的空值和签名参数
			String json4 = AlipayCore.createLinkString(map4); // 拼接后的字符串

			json4 = json4 + "&sign=" + URLEncoder.encode(rsaSign, "UTF-8");

			//logger.info(json4.toString());
			
			dataObj.put("payInfo", json4.toString());
			//logger.info(dataObj);

			object.put("resultCode", Constants.SUCCESS);
			object.put("resultDesc", "SUCCESS");
			object.put("data", dataObj);
		} catch (Exception e) {
			object.put("resultCode", Constants.EXCEPTION);
			object.put("resultDesc", Constants.EXCEPTION_DESC);
			logger.error(e.getMessage(),e);
		}
		return object.toString();
	}

	/**
	 * 接收支付宝支付的异步通知消息
	 * 
	 * @author Han Guohong
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(value = "/notify", produces = "text/plain;charset=UTF-8")
	public String notify(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		logger.info("-------------收到支付宝异步通知--------------");
		try {
			// 获取支付宝POST过来反馈信息
			Map<String, String> params = new HashMap<String, String>();
			Map requestParams = request.getParameterMap();
			for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
				String name = (String) iter.next();
				String[] values = (String[]) requestParams.get(name);
				String valueStr = "";
				for (int i = 0; i < values.length; i++) {
					valueStr = (i == values.length - 1) ? valueStr + values[i]
							: valueStr + values[i] + ",";
				}
				// 乱码解决，这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
				// valueStr = new String(valueStr.getBytes("ISO-8859-1"),
				// "gbk");
				logger.info("--支付宝回调--" + valueStr);
				params.put(name, valueStr);
			}

			// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
			// 商户订单号

			String out_trade_no = new String(request.getParameter(
					"out_trade_no").getBytes("ISO-8859-1"), "UTF-8");
			logger.info("--支付宝回调out_trade_no--" + out_trade_no);
			// 支付宝交易号

			String trade_no = new String(request.getParameter("trade_no")
					.getBytes("ISO-8859-1"), "UTF-8");
			logger.info("--支付宝回调trade_no--" + trade_no);
			// 交易状态
			String trade_status = new String(request.getParameter(
					"trade_status").getBytes("ISO-8859-1"), "UTF-8");
			logger.info("--支付宝回调trade_status--" + trade_status);

			/*
			 * String total_fee = new String(request.getParameter("total_fee")
			 * .getBytes("ISO-8859-1"), "UTF-8");
			 * logger.info("--支付宝回调total_fee--" + total_fee);
			 */

			String notify_time = new String(request.getParameter("notify_time")
					.getBytes("ISO-8859-1"), "UTF-8");
			logger.info("--支付宝回调notify_time--" + notify_time);

			// 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
			if (StringUtils.isNotEmpty(trade_status)
					&& trade_status.equals("WAIT_BUYER_PAY")) {
				response.getWriter().print("success");
				return null;
			}
			logger.info(params.toString());
			// AlipaySignature.rsaCheckV1(params, AlipayConfig.ali_public_key,
			// "utf-8");
			// if (AlipayNotify.verify(params)) {// 验证成功
			if (AlipaySignature.rsaCheckV1(params, AlipayConfig.ali_public_key,
					"utf-8")) {
				logger.info("-------------支付宝支付验证成功--------------");
				// ////////////////////////////////////////////////////////////////////////////////////////
				// 请在这里加上商户的业务逻辑程序代码

				// ——请根据您的业务逻辑来编写程序（以下代码仅作参考）——

				if (trade_status.equals("TRADE_FINISHED")) {
					logger.info("-------------TRADE_FINISHED--------------");
					// 判断该笔订单是否在商户网站中已经做过处理
					// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					// 如果有做过处理，不执行商户的业务程序

					// 注意：
					// 该种交易状态只在两种情况下出现
					// 1、开通了普通即时到账，买家付款成功后。
					// 2、开通了高级即时到账，从该笔交易成功时间算起，过了签约时的可退款时限（如：三个月以内可退款、一年以内可退款等）后。

					String payId = out_trade_no;
					PayStream stream = payStreamMapper.selectByPrimaryKey(payId);
					if(stream.getPayStatus() == 1){
						response.getWriter().print("success"); // 请不要修改或删除
					}else{
						OrderInfoExample example = new OrderInfoExample();
						com.jsz.peini.bean.order.OrderInfoExample.Criteria criteria = example.createCriteria();
						criteria.andPayStreamIdEqualTo(payId);
						List<OrderInfo> titles = orderInfoMapper.selectByExample(example);
						if (titles.size() >= 0) {
							for (OrderInfo title : titles) {
								if(title.getOrderType() == 1 || title.getOrderType() == 3){
									if(title.getOrderStatus() == 0){
										title.setOrderStatus(1);
										title.setPayStatus(1);
										title.setPayTime(new Date());
										orderInfoMapper.updateByPrimaryKeySelective(title);
										boolean flag = orderInfoService.notifyPayOrder(title);
									}
								}else if(title.getOrderType() == 6 || title.getOrderType() == 7){
									if(title.getOrderStatus() == 0){
										title.setOrderStatus(2);
										title.setPayStatus(1);
										title.setPayTime(new Date());
										boolean flag = orderInfoService.notifyPayOrder(title);
									}
								}else if(title.getOrderType() == OrderType.PARTY_PREPAY){
									partyService.setUserPrePayed(title);
								}else if(title.getOrderType() == OrderType.PARTY_ORDER || title.getOrderType() == OrderType.PARTY_PREPAY){
									partyService.setPartyPayed(title);
								}
								
								//response.getWriter().print("success"); // 请不要修改或删除
							}
						} else {
							response.getWriter().print("fail");
						}
						stream.setPayType(3);
						stream.setFinishTime(new Date());
						stream.setPayStatus(1);
						stream.setTransactionCode(trade_no);
						payStreamMapper.updateByPrimaryKey(stream);
						
						response.getWriter().print("success"); // 请不要修改或删除
					}
				} else if (trade_status.equals("TRADE_SUCCESS")) {
					logger.info("-------------TRADE_SUCCESS--------------");
					// 判断该笔订单是否在商户网站中已经做过处理
					// 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
					// 如果有做过处理，不执行商户的业务程序

					// 注意：
					// 该种交易状态只在一种情况下出现——开通了高级即时到账，买家付款成功后。
					String payId = out_trade_no;
					PayStream stream = payStreamMapper.selectByPrimaryKey(payId);
					if(stream.getPayStatus() == 1){
						response.getWriter().print("success"); // 请不要修改或删除
					}else{
						OrderInfoExample example = new OrderInfoExample();
						com.jsz.peini.bean.order.OrderInfoExample.Criteria criteria = example.createCriteria();
						criteria.andPayStreamIdEqualTo(payId);
						List<OrderInfo> titles = orderInfoMapper.selectByExample(example);
						if (titles.size() >= 0) {
							for (OrderInfo title : titles) {
								if(title.getOrderType() == 1 || title.getOrderType() == 3){
									if(title.getOrderStatus() == 0){
										title.setOrderStatus(1);
										title.setPayStatus(1);
										title.setPayTime(new Date());
										orderInfoMapper.updateByPrimaryKeySelective(title);
										boolean flag = orderInfoService.notifyPayOrder(title);
									}
								}else if(title.getOrderType() == 6){
									if(title.getOrderStatus() == 0){
										title.setOrderStatus(2);
										title.setPayStatus(1);
										title.setPayTime(new Date());
										orderInfoMapper.updateByPrimaryKeySelective(title);
										boolean flag = orderInfoService.notifyPayOrder(title);
									}
								}else if(title.getOrderType() == OrderType.PARTY_PREPAY){
									partyService.setUserPrePayed(title);
								}else if(title.getOrderType() == OrderType.PARTY_ORDER || title.getOrderType() == OrderType.PARTY_PREPAY){
									partyService.setPartyPayed(title);
								}
								
								//response.getWriter().print("success"); // 请不要修改或删除
							}
						} else {
							response.getWriter().print("fail");
						}
						stream.setPayType(3);
						stream.setFinishTime(new Date());
						stream.setPayStatus(1);
						stream.setTransactionCode(trade_no);
						payStreamMapper.updateByPrimaryKey(stream);
						
						response.getWriter().print("success"); // 请不要修改或删除
					}
				}

				// ////////////////////////////////////////////////////////////////////////////////////////
			} else {// 验证失败
				logger.info("-------------支付宝支付验证失败--------------");
				response.getWriter().print("fail");
			}
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
		}
		return null;
	}

}
